const csr = @import("riscv").csr;
const root = @import("kernel.zig");

const plic = @import("plic.zig");
const task = @import("task.zig");
const clint = @import("clint.zig");

const print = root.print;
extern fn trap_vector() callconv(.c) void;

pub fn init() void {
    // set the trap-vector base-address for machine-mode
    csr.mtvec.write(@intFromPtr(&trap_vector));
}

export fn trap_handler(epc: u32, mcause: csr.mcause.Type()) u32 {
    const return_pc: u32 = epc;
    print("\x1b[32m" ++ "{f}\n" ++ "\x1b[m", .{mcause});

    if (mcause.interrupt) {
        // Asynchronous trap - interrupt
        switch (mcause.code.interrupt) {
            .@"Machine software interrupt" => {
                clint.software.answer(0);
                task.schedule();
            },
            .@"Machine timer interrupt" => {
                clint.timer.handler();
            },
            .@"Machine external interrupt" => {
                plic.handler();
            },
            else => print("unknown async exception!\n", .{}),
        }
    } else {
        // Synchronous trap - exception
        @panic(@tagName(mcause.code.exception));
    }

    return return_pc;
}

pub fn tests() void {
    // Synchronous exception code = 7
    // Store/AMO access fault
    @as(*allowzero volatile usize, @ptrFromInt(0)).* = 100; // 加 volatile 才不会被优化

    // Synchronous exception code = 5
    // Load access fault
    const a = @as(*allowzero volatile usize, @ptrFromInt(0)).*;
    _ = a;

    print("Yeah! I'm return back from trap!\n", .{});
}
